﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using GemBox.Spreadsheet;

namespace pgen
{
    public partial class MainForm : Form
    {
        //private readonly Database database = new Database();
        private Settings _settings;
        private PinHistory _history;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            _settings = Settings.DeserializeFromXml("pgen.xml");
            _history = new PinHistory();
            _history.LoadFromFile("pgenhist.dat");

            trkPinLength.Value = _settings.PinLength;
            trkPinLength_ValueChanged(null, null);
            trkSerialLength.Value = _settings.SerialLength;
            trkSerialLength_Scroll(null, null);
            txtNumberOfPins.Value = _settings.PinCount;
            txtSerialStart.Value = _settings.SerialStart;
            saveFileDialog1.InitialDirectory = Environment.CurrentDirectory;
        }

        private void btnThousand_Click(object sender, EventArgs e)
        {
            var num = txtNumberOfPins.Value;
            num = num*1000;
            if (num > txtNumberOfPins.Maximum)
            {
                MessageBox.Show("Only 50,000 units are exported at a time");
                return;
            }
            txtNumberOfPins.Value = num;
        }

        private void btnHundred_Click(object sender, EventArgs e)
        {
            var num = txtNumberOfPins.Value;
            num = num * 100;
            if (num > txtNumberOfPins.Maximum)
            {
                MessageBox.Show("Only 50,000 units are exported at a time");
                return;
            }
            txtNumberOfPins.Value = num;
        }

        private void trkPinLength_ValueChanged(object sender, EventArgs e)
        {
            lblPinLen.Text = trkPinLength.Value.ToString();
        }

        private void trkSerialLength_Scroll(object sender, EventArgs e)
        {
            lblSerialLen.Text = trkSerialLength.Value.ToString();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            _settings.PinLength = trkPinLength.Value;
            _settings.SerialLength = trkSerialLength.Value;
            _settings.PinCount = (int) txtNumberOfPins.Value;
            _settings.SerialStart = (int) txtSerialStart.Value;

            _settings.SerializeToXml("pgen.xml");
            _history.SaveToFile("pgenhist.dat");
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            saveFileDialog1.Filter = "xls files (*.xls)|*.xls|All files (*.*)|*.*";
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                var xlsName = Path.ChangeExtension(saveFileDialog1.FileName, "xls");
                Cursor = Cursors.WaitCursor;
                try
                {
                    var list = GeneratePins();
                    GenerateXlsFile(xlsName, list, trkPinLength.Value, trkSerialLength.Value);
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }

        private Dictionary<string, string> GeneratePins()
        {
            var list = new Dictionary<string, string>();
            var count = (int)txtNumberOfPins.Value;
            var plen = trkPinLength.Value;
            var slen = trkSerialLength.Value;
            var sstart = (int)txtSerialStart.Value;

            var pin = new PinCode(plen);
            var sgen = new SerialCodeGenerator {Count = count, SerialLength = slen, SerialStart = sstart};
            //var lastSerial = 0;
            foreach (var serial in sgen)
            {
                pin.Seed();
                if (_history.PinIsUnique(pin))
                {
                    _history.AddToHistory(pin);
                    list.Add(pin.ToString(), string.Format("{0:0000}", serial));
                    //lastSerial = serial;
                }
            }
            //if (lastSerial > 0) txtSerialStart.Value = lastSerial;
            return list;
        }

        private static void GenerateXlsFile(string filename, Dictionary<string, string> list, int lenPinCode, int lenSerial)
        {
            var excelFile = new ExcelFile();
            var workSheet = excelFile.Worksheets.Add("Sheet1");
            var row = 0;

            string pinFormat = string.Empty, slFormat = string.Empty;
            
            for (var i = 0; i < lenPinCode; i++)
            {
                pinFormat += "0";
            }
            
            for (var i = 0; i < lenSerial; i++)
            {
                slFormat += "0";
            }
            
            foreach (var pair in list)
            {

                workSheet.Cells[row, 0].Style.NumberFormat = pinFormat;
                workSheet.Cells[row, 0].Value = long.Parse(pair.Key);
                workSheet.Cells[row, 1].Style.NumberFormat = slFormat;
                workSheet.Cells[row, 1].Value = int.Parse(pair.Value);
                row++;
            }

            excelFile.SaveXls(filename);
        }

        private static void GenerateCsvFile(string filename, Dictionary<string, string> list)
        {
            using (var stream = new StreamWriter(File.Open(filename, FileMode.Create)))
            {
                foreach (var pair in list)
                {
                    stream.WriteLine("{0},{1}", pair.Key, pair.Value);
                }
            }
        }

        private void btnCsv_Click(object sender, EventArgs e)
        {
            saveFileDialog1.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                var csvName = Path.ChangeExtension(saveFileDialog1.FileName, "csv");
                Cursor = Cursors.WaitCursor;
                try
                {
                    var list = GeneratePins();
                    GenerateCsvFile(csvName, list);
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }
    }
}